package com.app.core.dao;

import java.util.Date;
import java.util.Properties;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.app.core.dao.annotation.BaseEntityAnnotation;
import com.app.core.web.context.RequestContext;

@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class CCUUInterceptor implements Interceptor {

    final static Logger logger = LoggerFactory.getLogger(CCUUInterceptor.class);
    private static final String DEFAULT_CREATE_USER_FIELD = "createUser";
    private static final String DEFAULT_CREATE_DATE_FIELD = "createTime";
    private static final String DEFAULT_UPDATE_USER_FIELD = "updateUser";
    private static final String DEFAULT_UPDATE_DATE_FIELD = "updateTime";
    private static final String DEFAULT_IS_DEL_FIELD = "delFlag";

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
        Object parameter = invocation.getArgs()[1];

        Class<?> cl = parameter.getClass();
        for (; cl != null; cl = cl.getSuperclass()) {
            if (cl.getAnnotation(BaseEntityAnnotation.class) != null) {
                Date now = new Date();
                if (ms.getSqlCommandType() == SqlCommandType.INSERT) {
                    PropertyUtils.setProperty(parameter, getCreateUserField(), getOperationUser() + "");
                    PropertyUtils.setProperty(parameter, getCreateDateField(), now);
                    PropertyUtils.setProperty(parameter, getUpdateUserField(), getOperationUser() + "");
                    PropertyUtils.setProperty(parameter, getUpdateDateField(), now);
                    if(PropertyUtils.getProperty(parameter, DEFAULT_IS_DEL_FIELD) == null){
                        PropertyUtils.setProperty(parameter, DEFAULT_IS_DEL_FIELD, 0);
                    }
                } else if (ms.getSqlCommandType() == SqlCommandType.UPDATE) {
                    PropertyUtils.setProperty(parameter, getUpdateUserField(), getOperationUser() + "");
                    PropertyUtils.setProperty(parameter, getUpdateDateField(), now);
                }
                break;
            }
        }

        return invocation.proceed();
    }

    protected Object getOperationUser() {
        return RequestContext.getUserId();
    }

    protected String getCreateUserField() {
        return DEFAULT_CREATE_USER_FIELD;
    }

    protected String getCreateDateField() {
        return DEFAULT_CREATE_DATE_FIELD;
    }

    protected String getUpdateUserField() {
        return DEFAULT_UPDATE_USER_FIELD;
    }

    protected String getUpdateDateField() {
        return DEFAULT_UPDATE_DATE_FIELD;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        System.out.println("test");
    }
}
